# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, print_function
from backend import LOG
from backend.commons import catch_exception
from backend.tools.dw_img import orientation
from ..business_service.base import BusinessRequest
from ..business_service.sku import Sku
from ..ai_service import fc_map, ClassifyRequest
from ..model import classify_service_manager


class DetectRequest(BusinessRequest):
    """
    商品识别
    """

    def __init__(self, user_id, business_service_id, **kwargs):
        self.image = None
        self.sku_list = list()
        self.is_normal_shelf = ""
        self.is_normal_shelf_confidence = ""
        self.is_normal_shelf_coordinate = list()
        self.general_results = list()
        self.shelf_layers_lines = list()
        self.search_results = list()
        # 二次翻转识别所需的属性
        self.image_list = list()
        self.general_results_list = list()
        self.shelf_layers_list = list()
        self.search_results_list = list()
        self.max_idx = 0
        self.max_len = 0
        super().__init__(user_id, business_service_id, **kwargs)
        self.sku = Sku(self.business_service.cate)

    def set_sku_list(self):
        classify_service = classify_service_manager.select(
            ai_service_id=self.current_ai_service_obj.ai_service_id
        )
        if classify_service:
            self.sku_list = [_.as_dict()["class_name"] for _ in classify_service]
        # LOG.debug(f"sku_list={self.sku_list}")

    def set_quality_data(self, results):
        self.is_normal_shelf = results.get("is_normal_shelf", "")
        self.is_normal_shelf_confidence = results.get("is_normal_shelf_confidence", "")
        self.is_normal_shelf_coordinate = results.get("is_normal_shelf_coordinate", [0, 0, 0, 0])

    def set_general_data(self, results):
        self.general_results = eval(results.get("general_results", "[]"))
        self.shelf_layers_lines = eval(results.get("shelf_layers_lines", "[]"))

    def set_classify_data(self, results):
        self.search_results = eval(results.get("search_results", "[]"))

    def set_data(self, ai_service_type):
        if isinstance(self.current_ai_service_obj, fc_map[ai_service_type]):
            getattr(self, "set_%s_data" % ai_service_type)(
                self.current_ai_service_obj.wfw_response
            )

    def set_ai_service_obj_by_type(self, ai_service_type):
        ai_template_id = self.choose_ai_template(ai_service_type)
        for item in self.ai_service_chain:
            if item["type"] == ai_service_type:
                # 依据ai服务类型，实例化ai_service子类的对象
                return fc_map[item["type"]](item["ai_service_id"], ai_template_id)

    def redetect(self):
        self.image_list.append(self.image)
        self.general_results_list.append(self.general_results)
        self.shelf_layers_list.append(self.shelf_layers_lines)
        self.search_results_list.append(self.search_results)

        for item in self.search_results:
            if item[4] in self.sku.self_sku_list:
                self.max_len += 1

        for index, angle in enumerate([90, 180, 270]):
            image_new = orientation(self.image, angle)
            kwargs = dict(image=image_new)
            general = self.set_ai_service_obj_by_type("general")
            try:
                general(**kwargs)
                self.general_results_list.append(
                    general.wfw_response.get("general_results", [])
                )
                self.shelf_layers_list.append(
                    general.wfw_response.get("shelf_layers_lines", [])
                )
                self.image_list.append(image_new)
            except Exception:
                continue
            kwargs.update(
                dict(
                    general_results=general.wfw_response.get("general_results", []),
                    sku_names_list=self.sku_list,
                )
            )
            classify = self.set_ai_service_obj_by_type("classify")
            try:
                classify(**kwargs)
                self.search_results_list.append(
                    classify.wfw_response.get("search_results", [])
                )
            except Exception:
                continue
            self_sku_num = 0
            for item in classify.wfw_response.get("search_results", []):
                if item[4] in self.sku.self_sku_list:
                    self_sku_num += 1
            if self_sku_num > self.max_len:
                self.max_len = self_sku_num
                self.max_idx = index + 1
        self.general_results = self.general_results_list[self.max_idx]
        self.image = self.image_list[self.max_idx]
        self.search_results = self.search_results_list[self.max_idx]

    @catch_exception
    def detect(self, **kwargs):
        self.set_ai_service_objs()
        self.image = kwargs.get("image", None)
        for ai_service_obj in self.ai_service_objs:
            self.current_ai_service_obj = ai_service_obj
            self.update_current_ai_service()
            # 分类服务需要添加额外参数
            if isinstance(self.current_ai_service_obj, ClassifyRequest):
                self.set_sku_list()
                self.sku.set_skuinfo_by_sku_list(self.sku_list)
                kwargs.update(
                    dict(
                        # TODO: shinho classify 处理参数强转换，需更新classify微服务接口
                        general_results=str(self.general_results),
                        sku_names_list=str(self.sku_list),
                    )
                )
            self.current_ai_service_obj(**kwargs)
            if isinstance(self.current_ai_service_obj, ClassifyRequest):
                self.set_classify_data(self.current_ai_service_obj.wfw_response)
                # 本品个数小于35翻转识别
                # TODO: 模型以及AI服务迭代支持，从后端逻辑去掉
                # if len(self.search_results) < 35:
                #     self.redetect()
            self.update_completion_ratio()
            self.save_result()
            self.set_data(self.current_ai_service_obj.ai_service.type)
        if self.completion_count == len(self.ai_service_chain):
            self.save_request_done()
